package com.revolsys.gis.web.rest.converter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletWebRequest;
import com.revolsys.geometry.model.Geometry;
import com.revolsys.geometry.model.GeometryFactory;
import com.revolsys.io.IoConstants;
import com.revolsys.io.IoFactory;
import com.revolsys.io.Reader;
import com.revolsys.io.Writer;
import com.revolsys.record.Record;
import com.revolsys.record.io.RecordReader;
import com.revolsys.record.io.RecordReaderFactory;
import com.revolsys.record.io.RecordWriterFactory;
import com.revolsys.record.io.format.kml.Kml22Constants;
import com.revolsys.record.schema.RecordDefinition;
import com.revolsys.spring.resource.InputStreamResource;
import com.revolsys.ui.web.rest.converter.AbstractHttpMessageConverter;
import com.revolsys.ui.web.utils.HttpServletUtils;
public class RecordReaderHttpMessageConverter extends AbstractHttpMessageConverter<RecordReader> {
private GeometryFactory geometryFactory;
private List<String> requestAttributeNames = Arrays.asList(IoConstants.SINGLE_OBJECT_PROPERTY,
Kml22Constants.STYLE_URL_PROPERTY, Kml22Constants.LOOK_AT_POINT_PROPERTY,
Kml22Constants.LOOK_AT_RANGE_PROPERTY, Kml22Constants.LOOK_AT_MIN_RANGE_PROPERTY,
Kml22Constants.LOOK_AT_MAX_RANGE_PROPERTY, IoConstants.JSONP_PROPERTY,
IoConstants.TITLE_PROPERTY, IoConstants.DESCRIPTION_PROPERTY);
public RecordReaderHttpMessageConverter() {
super(RecordReader.class, IoFactory.mediaTypes(RecordReaderFactory.class),
IoFactory.mediaTypes(RecordWriterFactory.class));
}
public GeometryFactory getGeometryFactory() {
return this.geometryFactory;
}
public List<String> getRequestAttributeNames() {
return this.requestAttributeNames;
}
@Override
public RecordReader read(final Class<? extends RecordReader> clazz,
final HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
try {
final HttpHeaders headers = inputMessage.getHeaders();
final MediaType mediaType = headers.getContentType();
Charset charset = mediaType.getCharSet();
if (charset == null) {
charset = StandardCharsets.UTF_8;
}
final InputStream body = inputMessage.getBody();
final String mediaTypeString = mediaType.getType() + "/" + mediaType.getSubtype();
final RecordReaderFactory readerFactory = IoFactory
.factoryByMediaType(RecordReaderFactory.class, mediaTypeString);
if (readerFactory == null) {
throw new HttpMessageNotReadableException("Cannot read data in format" + mediaType);
} else {
final Reader<Record> reader = readerFactory
.newRecordReader(new InputStreamResource("recordInput", body));
GeometryFactory factory = this.geometryFactory;
final ServletWebRequest requestAttributes = (ServletWebRequest)RequestContextHolder
.getRequestAttributes();
final String srid = requestAttributes.getParameter("srid");
if (srid != null && srid.trim().length() > 0) {
factory = GeometryFactory.floating3(Integer.parseInt(srid));
}
reader.setProperty(IoConstants.GEOMETRY_FACTORY, factory);
return (RecordReader)reader;
}
} catch (final IOException e) {
throw new HttpMessageNotReadableException("Error reading data", e);
}
}
public void setGeometryFactory(final GeometryFactory geometryFactory) {
this.geometryFactory = geometryFactory;
}
public void setRequestAttributeNames(final List<String> requestAttributeNames) {
this.requestAttributeNames = requestAttributeNames;
}
@Override
public void write(final RecordReader reader, final MediaType mediaType,
final HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
if (!HttpServletUtils.getResponse().isCommitted()) {
MediaType actualMediaType;
if (mediaType == null) {
actualMediaType = getDefaultMediaType();
} else {
actualMediaType = mediaType;
}
if (actualMediaType != null) {
final Charset charset = HttpServletUtils.setContentTypeWithCharset(outputMessage,
actualMediaType);
final String mediaTypeString = actualMediaType.getType() + "/"
+ actualMediaType.getSubtype();
final RecordWriterFactory writerFactory = IoFactory
.factoryByMediaType(RecordWriterFactory.class, mediaTypeString);
if (writerFactory == null) {
throw new IllegalArgumentException("Media type " + actualMediaType + " not supported");
} else {
final RecordDefinition recordDefinition = reader.getRecordDefinition();
final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
String baseName = (String)requestAttributes.getAttribute("contentDispositionFileName",
RequestAttributes.SCOPE_REQUEST);
if (baseName == null) {
baseName = HttpServletUtils.getRequestBaseFileName();
}
String contentDisposition = (String)requestAttributes.getAttribute("contentDisposition",
RequestAttributes.SCOPE_REQUEST);
if (contentDisposition == null) {
contentDisposition = "attachment";
}
final String fileName = baseName + "." + writerFactory.getFileExtension(mediaTypeString);
final HttpHeaders headers = outputMessage.getHeaders();
headers.set("Content-Disposition", contentDisposition + "; filename=" + fileName);
final OutputStream body = outputMessage.getBody();
final Writer<Record> writer = writerFactory.newRecordWriter(baseName, recordDefinition,
body, charset);
if (Boolean.FALSE
.equals(requestAttributes.getAttribute("wrapHtml", RequestAttributes.SCOPE_REQUEST))) {
writer.setProperty(IoConstants.WRAP_PROPERTY, false);
}
final HttpServletRequest request = HttpServletUtils.getRequest();
String callback = request.getParameter("jsonp");
if (callback == null) {
callback = request.getParameter("callback");
}
if (callback != null) {
writer.setProperty(IoConstants.JSONP_PROPERTY, callback);
}
for (final String attributeName : requestAttributes
.getAttributeNames(RequestAttributes.SCOPE_REQUEST)) {
final Object value = requestAttributes.getAttribute(attributeName,
RequestAttributes.SCOPE_REQUEST);
if (value != null && attributeName.startsWith("java:")
|| this.requestAttributeNames.contains(attributeName)) {
writer.setProperty(attributeName, value);
}
}
final Iterator<Record> iterator = reader.iterator();
if (iterator.hasNext()) {
Record record = iterator.next();
final Geometry geometry = record.getGeometry();
if (geometry != null) {
final GeometryFactory geometryFactory = geometry.getGeometryFactory();
writer.setProperty(IoConstants.GEOMETRY_FACTORY, geometryFactory);
}
writer.write(record);
while (iterator.hasNext()) {
record = iterator.next();
writer.write(record);
}
}
writer.close();
}
}
}
}
}